package IO.序列化;

import java.util.List;
import com.alibaba.fastjson2.JSON;
import lombok.Data;

//import com.alibaba.fastjson2.JSON;

/*
一、fastjson入门
以下内容来源：https://github.com/alibaba/fastjson/wiki/Quick-Start-CN
它可以解析JSON格式的字符串，支持将Java Bean序列化为JSON字符串，也可以从JSON字符串反序列化到JavaBean

json:
{
	"id":3y,
	"desc":"公众号：java3y";
	"name":"三歪"：
	"label":"3y";
	"value":{
		"value":"1182749263",
		"emphasic":""
	}
}

javaBean:
public class MyGongZhongHao{
	private String id;
	private String desc;
	private String label;
	private Object value;
}

javaBean --> json:序列化
json --> javaBean：反序列化


fastjson优点：速度快、使用广泛、使用简单、功能完备、测试完备（之前爆了很多漏洞，现在我司走发布流程都强制我们升级fastjson版本了），现在使
用fastjson至少升级到12.0.33版本

速度快的原因：

1、自行编写类似StringBuilder的工具类SerializeWriter。
2、使用ThreadLocal来缓存buf。
3、使用asm避免反射
4、集成jdk实现的一些优化算法

二、使用fastjson
首先我们在pom文件中引入fastjson的依赖就好了：

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>x.x.x</version>
</dependency>
fastjson的使用主要是三个对象：

•JSON
•JSONObject
•JSONArray

JSONArray和JSONObject继承JSON：
JSON-->JSONArray
    -->JSONObject

2.1 JSON对象
JSON这个类主要用于转换：
•将Java对象序列化为JSON字符串
•将JSON字符串反序列化为Java对象

所以，有三个方法我们用得特别多：
•parseObject(String text, Class<T> clazz)
•parseArray(String text, Class<T> clazz)
•toJSONString(Object object)

2.2 JSONObject
JSON对象(JSONObject)中的数据都是以key-value形式出现，所以它实现了Map接口：

JSONObject-->Map
          -->JSON
          -->Cloneable
          -->InvocationHandler

JSONObject-->Map使用起来也很简单，跟使用Map就没多大的区别（因为它底层实际上就是操作Map)，常用的方法：

•getString(String key)
•remove(Object key)

1.put(String key, Object value)方法，在JSONObject对象中设置键值对在，在进行设值得时候，key是唯一的，如果用相同的key不断设值得时候，保留后面的值。
2.Object get(String key) :根据key值获取JSONObject对象中对应的value值，获取到的值是Object类型，需要手动转化为需要的数据类型
3.int size():获取JSONObject对象中键值对的数量
4.boolean isEmpty()：判断该JSONObject对象是否为空
5.containsKey(Object key)：判断是否有需要的key值
6.boolean containsValue(Object value)：判断是否有需要的value值
7.JSONObject getJSONObject(String key)：如果JSONObjct对象中的value是一个JSONObject对象，即根据key获取对应的JSONObject对象；
8.JSONArray getJSONArray(String key) ：如果JSONObject对象中的value是一个JSONObject数组，既根据key获取对应的JSONObject数组；
9.Object remove(Object key)：根据key清除某一个键值对。
由于JSONObject是一个map，它还具有map特有的两个方法：
10.Set<String> keySet() ：获取JSONObject中的key，并将其放入Set集合中
11.Set<Map.Entry<String, Object>> entrySet()：在循环遍历时使用，取得是键和值的映射关系，Entry就是Map接口中的内部接口
与String字符串转换：
12.toJSONString() /toString():将JSONObject对象转换为json的字符串
例子：
public static void main(String[] args) {
        //新建JSONObject对象
        JSONObject object1 = new JSONObject();
        
        //1.在JSONObject对象中放入键值对
        object1.put("name", "张三");
        object1.put("name1", "张三1");
        object1.put("name2", "张三2");
        
        //2.根据key获取value
        String name = (String) object1.get("name");
        System.out.println(name);
        
        //3.获取JSONObject中的键值对个数
        int size = object1.size();
        System.out.println(size);
        
        //4.判断是否为空
        boolean result = object1.isEmpty();
        System.out.println(result);
        
        //5.是否包含对应的key值，包含返回true，不包含返回false
        boolean isContainsKeyResult = object1.containsKey("name");
        System.out.println(isContainsKeyResult);
        
        //6.是否包含对应的value值，包含返回true，不包含返回false
        boolean isContainsValueResult = object1.containsValue("王五");
        System.out.println(isContainsValueResult);
        
        //7.JSONObjct对象中的value是一个JSONObject对象，即根据key获取对应的JSONObject对象；
        JSONObject object2 = new JSONObject();
        //将jsonobject对象作为value进行设置
        object2.put("student1", object1);
        JSONObject student =object2.getJSONObject("student1");
        System.out.println(student);
        
        //8.如果JSONObject对象中的value是一个JSONObject数组，既根据key获取对应的JSONObject数组；
        JSONObject objectArray = new JSONObject();
        //创建JSONArray数组
        JSONArray jsonArray = new JSONArray();
        //在JSONArray数组设值:jsonArray.add(int index, Object value);
        jsonArray.add(0, "this is a jsonArray value");
        jsonArray.add(1, "another jsonArray value");
        objectArray.put("testArray", jsonArray);
        //获取JSONObject对象中的JSONArray数组
        JSONArray jsonArray2 = objectArray.getJSONArray("testArray");
        System.out.println(jsonArray2);
        
        //9.remove.根据key移除JSONObject对象中的某个键值对
        object1.remove("name");
        System.out.println(object1);
        
        //10.取得JSONObject对象中key的集合
        Set<String> keySet= object1.keySet();
        for (String key : keySet) {
            System.out.print("   "+key);
        }
        System.out.println();
        
        //11.取得JSONObject对象中的键和值的映射关系
        Set<Map.Entry<String, Object>> entrySet = object1.entrySet();
        for (Entry<String, Object> entry : entrySet) {
            System.out.println(entry);
        }
        
        //12.转换为json字符串
        String str1 = object1.toJSONString();
        System.out.println(str1);
        String str2 =object1.toString();
        System.out.println(str2);
    }



2.3 JSONArray
JSONArray则是JSON数组，JSON数组对象中存储的是一个个JSON对象，所以类中的方法主要用于直接操作JSON对象

JSONArray-->List
          -->JSON
          -->Cloneable
          -->randomAccess

最常用的方法：getJSONObject(int index)

## 三、实战

从上面的简单介绍我们已经可以知道了：

•JSON用于将字符串反序列化为JavaBean和JavaBean序列化为JSON
•JSONObject代表的是JSON对象，底层通过Map来操作，常用getString等方法来获取对应的值
•JSONArray代表的是JSON对象数组，底层实际上是List，它用作于操作JSON对象

一般来说，我们从数据库拿到JSON数据以后，然后要对JSON进行修改。比如JSON串如下：

{
    "formId": "{$formId}",
    "link": "www.java3y.com",
    "text": [{
        "name": "java3y",
        "label": "3y",
        "value": {
            "value": "{$tureName}",
            "color": "",
            "emphasis": ""
        }
    }, {
        "name": "java4y",
        "label": "3y",
        "value": {
            "value": "{$title}",
            "color": "",
            "emphasis": ""
        }
    }, {
        "name": "java5y",
        "label": "5y",
        "value": {
            "value": "关注我的公众号，更多干货",
            "color": "#ff0040",
            "emphasis": ""
        }
    }],
    "yyyImg": "",
    "yyyAge": "",
    "pagepath": ""
}
我们是不会直接操作JSON的，我们会将JSON转成我们自己的JavaBean，再操作JavaBean，最后序列化为JSONString

从上面的JSON结构上来看还是相对复杂的，思路：

•我们可以根据JSON的结构构建对应的JavaBean
•使用JSON类将JSON字符串反序列化为JavaBean
•修改JavaBean的值
•最后将JavaBean序列化为JSON字符串

从上面的JSON结构，首先我们针对text这层抽象为一个JavaBean。（实际上最里层的结构是value，但我这边不需要处理value，所以就不抽象了）
*/
/**
 * "name": "java3y",
 *  "label": "3y",
 *  "value": {
 *      "value": "{$tureName}",
 *      "color": "",
 *      "emphasis": ""
 *    }
 *
 *  对Text进行抽象
 */
@Data
class TextInfo {

    private String name;
    private String label;

    // 因为value我这边不需要操作，所以就不抽象了，如果每层都要处理，那就得抽象
    private Object value;


    // set get ... 省略 欢迎关注我的公众号：Javay

}
//然后对外层进行抽象：
@Data
class ContentValue {
    private String formId;
    private String link;
    // 这里是一个数组，我们就抽象为List，属性名为text
    private List<TextInfo> text;

    private String yyyImg;
    private String yyyAge;
    private String pagepath;
}
//我们反序列化看一下：
/*
public class fastjson使用 {
	public static void main(String[] args) {

    // JSON 字符串
    String s = "{\"formId\":\"{$formId}\",\"link\":\"www.java3y.com\",\"text\":[{\"name\":\"java3y\",\"label\":\"3y\",\"value\":{\"value\":\"{$tureName}\",\"color\":\"\",\"emphasis\":\"\"}},{\"name\":\"java4y\",\"label\":\"3y\",\"value\":{\"value\":\"{$title}\",\"color\":\"\",\"emphasis\":\"\"}},{\"name\":\"java5y\",\"label\":\"5y\",\"value\":{\"value\":\"关注我的公众号，更多干货\",\"color\":\"#ff0040\",\"emphasis\":\"\"}}],\"yyyImg\":\"\",\"yyyAge\":\"\",\"pagepath\":\"\"}";

    // 使用JSON对象 将JSON字符串反序列化为JavaBean
    ContentValue contentValue = JSON.parseObject(s, ContentValue.class);
    System.out.println(contentValue);
    }
}*/
//反序列化结果：
//ContentValue(formId={$formId}, link=www.java3y.com, text=[IO.序列化.TextInfo@27a5f880, IO.序列化.TextInfo@1d29cf23, IO.序列化.TextInfo@5f282abb], yyyImg=, yyyAge=, pagepath=)


//我们要改text里边的值，只需要操作JavaBean就好了：
public class fastjson使用 {
public static void main(String[] args) {

    // JSON 字符串
    String s = "{\"formId\":\"{$formId}\",\"link\":\"www.java3y.com\",\"text\":[{\"name\":\"java3y\",\"label\":\"3y\",\"value\":{\"value\":\"{$tureName}\",\"color\":\"\",\"emphasis\":\"\"}},{\"name\":\"java4y\",\"label\":\"3y\",\"value\":{\"value\":\"{$title}\",\"color\":\"\",\"emphasis\":\"\"}},{\"name\":\"java5y\",\"label\":\"5y\",\"value\":{\"value\":\"关注我的公众号，更多干货\",\"color\":\"#ff0040\",\"emphasis\":\"\"}}],\"yyyImg\":\"\",\"yyyAge\":\"\",\"pagepath\":\"\"}";

    // 使用JSON对象 将JSON字符串反序列化为JavaBean
    ContentValue contentValue = JSON.parseObject(s, ContentValue.class);
    List<TextInfo> text = contentValue.getText();
    for (TextInfo textInfo : text) {
        textInfo.setName("Java3y");
        textInfo.setLabel("关注我的公众号呗");
    }

    // 修改后，反序列化回去
    String content = JSON.toJSONString(contentValue);
    System.out.println(content);
	}
}
//序列化结果：
//{"formId":"{$formId}","link":"www.java3y.com","pagepath":"","text":[{"label":"关注我的公众号呗","name":"Java3y","value":{"value":"{$tureName}","color":"","emphasis":""}},{"label":"关注我的公众号呗","name":"Java3y","value":{"value":"{$title}","color":"","emphasis":""}},{"label":"关注我的公众号呗","name":"Java3y","value":{"value":"关注我的公众号，更多干货","color":"#ff0040","emphasis":""}}],"yyyAge":"","yyyImg":""}

